#include "pbirsm.hpp"

// -----------------------------------------------------------
// PBIRSM (Parameter Buffer Interface and Raster Setup Module) 模块实现
// 职责：从DDR读取三角形参数，并流式输出给HR模块
// -----------------------------------------------------------
void parameter_buffer_interface_and_raster_setup(
    ddr_word_t* params_buffer_base_addr, // 指向DDR中三角形参数缓冲区的 64 位 AXI Master
    hls::stream<raster_params_packet_fixed>& output_raster_params_stream, // 输出到HR模块的三角形参数流
    const ap_uint<16> num_triangles_to_process // 本帧需要处理的三角形数量，由PS写入
) {
    #pragma HLS INTERFACE s_axilite port=params_buffer_base_addr bundle=ctrl_s_axilite_pbirsm
    #pragma HLS INTERFACE s_axilite port=num_triangles_to_process bundle=ctrl_s_axilite_pbirsm
    #pragma HLS INTERFACE s_axilite port=return bundle=ctrl_s_axilite_pbirsm

    #pragma HLS INTERFACE m_axi port=params_buffer_base_addr offset=slave bundle=m_axi_gmem_params_read max_read_burst_length=8
    #pragma HLS INTERFACE axis port=output_raster_params_stream

    #pragma HLS DATAFLOW

    ap_uint<PACKED_RASTER_PARAMS_BITS> raw_packet_data;

    TRIANGLE_READ_LOOP:
    for (ap_uint<16> triangle_idx = 0; triangle_idx < num_triangles_to_process; ++triangle_idx) {
        #pragma HLS LOOP_TRIPCOUNT min=500 max=2000
        #pragma HLS PIPELINE II=NUM_AXI_WORDS_PER_PACKET

        ap_uint<32> current_word_offset = triangle_idx * NUM_AXI_WORDS_PER_PACKET;

        READ_WORDS_LOOP:
        for (int i = 0; i < NUM_AXI_WORDS_PER_PACKET; ++i) {
            #pragma HLS UNROLL
            ddr_word_t ddr_word = params_buffer_base_addr[current_word_offset + i];
            raw_packet_data((i + 1) * AXI_STREAM_WORD_BITS - 1, i * AXI_STREAM_WORD_BITS) = ddr_word;
        }

        raster_params_packet_fixed current_triangle_params;
        int bit_offset = 0;

        // v0_x, v0_y, v1_x, v1_y, v2_x, v2_y (6 * fp_coord_t = 6 * 34 = 204 bits)
        // 将提取的 34 位位段强制转换为 ap_int<34>，确保符号位正确解释
        current_triangle_params.v0_x = (ap_int<34>)raw_packet_data(bit_offset + 33, bit_offset); bit_offset += 34;
        current_triangle_params.v0_y = (ap_int<34>)raw_packet_data(bit_offset + 33, bit_offset); bit_offset += 34;
        current_triangle_params.v1_x = (ap_int<34>)raw_packet_data(bit_offset + 33, bit_offset); bit_offset += 34;
        current_triangle_params.v1_y = (ap_int<34>)raw_packet_data(bit_offset + 33, bit_offset); bit_offset += 34;
        current_triangle_params.v2_x = (ap_int<34>)raw_packet_data(bit_offset + 33, bit_offset); bit_offset += 34;
        current_triangle_params.v2_y = (ap_int<34>)raw_packet_data(bit_offset + 33, bit_offset); bit_offset += 34;

        // v0_z, v1_z, v2_z (3 * fp_z_buffer_t = 3 * 16 = 48 bits)
        current_triangle_params.v0_z = raw_packet_data(bit_offset + 15, bit_offset); bit_offset += 16;
        current_triangle_params.v1_z = raw_packet_data(bit_offset + 15, bit_offset); bit_offset += 16;
        current_triangle_params.v2_z = raw_packet_data(bit_offset + 15, bit_offset); bit_offset += 16;

        // edge0_A, B, C; edge1_A, B, C; edge2_A, B, C (9 * fp_coord_t = 9 * 34 = 306 bits)
        current_triangle_params.edge0_A = (ap_int<34>)raw_packet_data(bit_offset + 33, bit_offset); bit_offset += 34;
        current_triangle_params.edge0_B = (ap_int<34>)raw_packet_data(bit_offset + 33, bit_offset); bit_offset += 34;
        current_triangle_params.edge0_C = (ap_int<34>)raw_packet_data(bit_offset + 33, bit_offset); bit_offset += 34;
        current_triangle_params.edge1_A = (ap_int<34>)raw_packet_data(bit_offset + 33, bit_offset); bit_offset += 34;
        current_triangle_params.edge1_B = (ap_int<34>)raw_packet_data(bit_offset + 33, bit_offset); bit_offset += 34;
        current_triangle_params.edge1_C = (ap_int<34>)raw_packet_data(bit_offset + 33, bit_offset); bit_offset += 34;
        current_triangle_params.edge2_A = (ap_int<34>)raw_packet_data(bit_offset + 33, bit_offset); bit_offset += 34;
        current_triangle_params.edge2_B = (ap_int<34>)raw_packet_data(bit_offset + 33, bit_offset); bit_offset += 34;
        current_triangle_params.edge2_C = (ap_int<34>)raw_packet_data(bit_offset + 33, bit_offset); bit_offset += 34;

        // dzdx, dzdy (2 * fp_coord_t = 2 * 34 = 68 bits)
        current_triangle_params.dzdx = (ap_int<34>)raw_packet_data(bit_offset + 33, bit_offset); bit_offset += 34;
        current_triangle_params.dzdy = (ap_int<34>)raw_packet_data(bit_offset + 33, bit_offset); bit_offset += 34;

        // pure_color_R, G, B (3 * fp_color_channel_t = 3 * 8 = 24 bits)
        current_triangle_params.pure_color_R = raw_packet_data(bit_offset + 7, bit_offset); bit_offset += 8;
        current_triangle_params.pure_color_G = raw_packet_data(bit_offset + 7, bit_offset); bit_offset += 8;
        current_triangle_params.pure_color_B = raw_packet_data(bit_offset + 7, bit_offset); bit_offset += 8;

        output_raster_params_stream.write(current_triangle_params);
    }
}
